package com.hawk.eye.server.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hawk.eye.common.model.ServiceMetadata;
import com.hawk.eye.framework.utils.CollectionUtil;
import com.hawk.eye.framework.utils.ExceptionUtils;
import com.hawk.eye.framework.utils.SecurityUtils;
import com.hawk.eye.framework.utils.StreamUtil;
import com.hawk.eye.common.utils.StringUtil;
import com.hawk.eye.framework.cache.ICache;
import com.hawk.eye.framework.core.domain.entity.SysUser;
import com.hawk.eye.common.page.PageQuery;
import com.hawk.eye.common.page.PageResult;
import com.hawk.eye.server.convert.ServiceConfigConvert;
import com.hawk.eye.server.domain.dto.req.ServiceConfigReqDTO;
import com.hawk.eye.server.domain.dto.resp.ServiceConfigDetailRespDTO;
import com.hawk.eye.server.domain.dto.resp.ServiceConfigRespDTO;
import com.hawk.eye.server.domain.po.OuterServiceWebhook;
import com.hawk.eye.server.domain.po.ServiceConfig;
import com.hawk.eye.common.utils.Kv;
import com.hawk.eye.server.mapper.OuterServiceWebhookMapper;
import com.hawk.eye.server.mapper.OuterWebhookMapper;
import com.hawk.eye.server.mapper.SysUserMapper;
import com.hawk.eye.server.service.IOuterServiceWebhookService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.hawk.eye.server.mapper.ServiceConfigMapper;
import com.hawk.eye.server.service.IServiceConfigService;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author salad
 * @date 2023-09-23
 */
@Service
@RequiredArgsConstructor
public class ServiceConfigServiceImpl extends ServiceImpl<ServiceConfigMapper, ServiceConfig> implements IServiceConfigService {

    private final ServiceConfigMapper serviceConfigMapper;

    private final IOuterServiceWebhookService serviceWebhookService;

    private final SysUserMapper userMapper;

    @Override
    public PageResult<ServiceConfigRespDTO> page(PageQuery pageQuery, ServiceConfigReqDTO reqDTO) {
        ExceptionUtils.isEmptyThrow(reqDTO.getGroupId(), "参数{}不允许为空", "groupId");
        if (reqDTO.getChargeUserId() != null && reqDTO.getChargeUserId() == -1L) {
            reqDTO.setChargeUserId(SecurityUtils.getUserId());
        }
        IPage<ServiceConfigRespDTO> pages = serviceConfigMapper.page(pageQuery.toPage(), reqDTO);
        return PageResult.of(pages);
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public boolean save(ServiceConfigReqDTO reqDTO) {
        long count = getServiceZnNameCount(reqDTO);
        ExceptionUtils.isTrueThrow(count > 0, "服务名[{}]已存在，请勿重复创建", reqDTO.getServiceZnName());
        ServiceConfig sc = ServiceConfigConvert.INSTANCE.reqDtoToPo(reqDTO);
        boolean success = save(sc);
        Long outerWebhookId = reqDTO.getOuterWebhookId();
        OuterServiceWebhook osw = new OuterServiceWebhook(null, sc.getId(), outerWebhookId);
        serviceWebhookService.save(osw);
        return success;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public boolean update(ServiceConfigReqDTO reqDTO) {
        ExceptionUtils.isEmptyThrow(reqDTO.getId(), "参数{}不允许为空", "id");
        long count = getServiceZnNameCount(reqDTO);
        ExceptionUtils.isTrueThrow(count > 0, "服务名[{}]已存在，请勿重复创建", reqDTO.getServiceZnName());
        boolean success = updateById(ServiceConfigConvert.INSTANCE.reqDtoToPo(reqDTO));
        serviceWebhookService.remove(Wrappers.<OuterServiceWebhook>lambdaQuery()
                .eq(OuterServiceWebhook::getServiceId, reqDTO.getId()));
        if (reqDTO.getOuterWebhookId() != null) {
            Long outerWebhookId = reqDTO.getOuterWebhookId();
            OuterServiceWebhook osw = new OuterServiceWebhook(null, reqDTO.getId(), outerWebhookId);
            serviceWebhookService.save(osw);
        }
        return success;
    }

    @Override
    public long getServiceZnNameCount(ServiceConfigReqDTO reqDTO) {
        return count(Wrappers.<ServiceConfig>lambdaQuery()
                .eq(ServiceConfig::getServiceZnName, reqDTO.getServiceZnName())
                .ne(reqDTO.getId() != null, ServiceConfig::getId, reqDTO.getId()));
    }

    @Override
    public ServiceConfigDetailRespDTO detail(Long id) {
        ExceptionUtils.isEmptyThrow(id, "参数{}不允许为空", "id");
        ServiceConfig serviceConfig = getById(id);
        ExceptionUtils.isEmptyThrow(serviceConfig, "查询不到该[{}]服务的配置信息，请刷新页面重试", id);
        //查询下面的模块信息
        ServiceConfigDetailRespDTO sc = ServiceConfigConvert.INSTANCE.to(serviceConfig);
        OuterServiceWebhook osw = serviceWebhookService.getOne(Wrappers.<OuterServiceWebhook>lambdaQuery()
                .eq(OuterServiceWebhook::getServiceId, id).last("limit 1"));
        if (osw != null) {
            sc.setOuterWebhookId(osw.getWebhookId());
        }
        return sc;
    }

    @Override
    public ServiceConfig getServiceConfig(ServiceMetadata serviceMetadata) {
        return getOne(Wrappers.<ServiceConfig>lambdaQuery()
                .eq(ServiceConfig::getServiceZnName, serviceMetadata.getServiceName())
                .orderByDesc(ServiceConfig::getCreateTime)
                .last("limit 1"));
    }

    @Override
    public ServiceConfig getServiceConfig(Long serviceId) {
        return getById(serviceId);
    }

    @Override
    public ServiceConfig getServiceConfig(String serviceZnName) {
        return getOne(Wrappers.<ServiceConfig>lambdaQuery()
                .eq(ServiceConfig::getServiceZnName, serviceZnName)
                .orderByDesc(ServiceConfig::getCreateTime).last("limit 1"));
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public boolean changeStatus(ServiceConfigReqDTO reqVoToReqDto) {
        ExceptionUtils.isEmptyThrow(reqVoToReqDto.getId(), "ID为必填项");
        ServiceConfig serviceConfig = getById(reqVoToReqDto.getId());
        ExceptionUtils.isEmptyThrow(serviceConfig, "查询不到该[{}]服务的配置信息，请刷新页面重试", reqVoToReqDto.getId());
        serviceConfig.setDisenabled(reqVoToReqDto.getDisenabled());
        return updateById(serviceConfig);
    }


    @Override
    public List<Kv> nameList() {
        List<ServiceConfig> serviceConfigs = baseMapper.selectList(Wrappers.<ServiceConfig>lambdaQuery()
                .select(ServiceConfig::getId, ServiceConfig::getServiceCnName, ServiceConfig::getServiceZnName));
        if (CollectionUtil.isEmpty(serviceConfigs)) {
            return new ArrayList<>();
        }

        return StreamUtil.mapToList(serviceConfigs.stream(), item -> {
            Kv kv = Kv.create();
            kv.set("id", item.getId());
            kv.set("name", item.getServiceCnName() + "(" + item.getServiceZnName() + ")");
            return kv;
        });
    }

    @Override
    public List<ServiceConfigRespDTO> getServiceConfigByGroup(Long id) {
        List<ServiceConfig> serviceConfigs = serviceConfigMapper
                .selectList(Wrappers.<ServiceConfig>lambdaQuery().eq(ServiceConfig::getGroupId, id));
        return ServiceConfigConvert.INSTANCE.to(serviceConfigs);
    }

    @Override
    public List<Kv> userList() {
        List<SysUser> userList = userMapper.selectUserList(new SysUser());
        return userList.stream()
                .map(e -> Kv.create().set("userId", e.getUserId()).set("name", e.getNickName()))
                .collect(Collectors.toList());
    }

    @Override
    public List<Kv> userListNotSelf() {
        List<SysUser> userList = userMapper.selectUserList(new SysUser());
        return userList.stream()
                .filter(e -> !SecurityUtils.getUserId().equals(e.getUserId()))
                .map(e -> Kv.create().set("userId", e.getUserId()).set("name", e.getNickName()))
                .collect(Collectors.toList());
    }

}
